package com.wangdong.yating.okhttp3;

import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import com.wangdong.yating.R;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import okhttp3.Authenticator;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Credentials;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.Route;

/**
 * 请求：每一个 HTTP请求中都包含一个URL，
 * 一个方法（如GET或POST），
 * 和一个请求头列表（headers）。
 * 请求还可以含有一个请求体（body）：
 * 一个特定内容类型的数据流。
 * <p>
 * 响应：每一个HTTP响应中都包含一个状态码（如200代表成功，404代表未找??到），
 * 一个响应头列表（headers）
 * 和一个可选的响应体（body）。
 *
 *
 *                  先还是简单所列一下几中调用方式的常见解释：

                    同步：函数没有执行完不返回，线程被挂起；　
                                        （就是在发出一个功能调用时，在没有得到结果之前，该调用就不返回。也就是必须一件一件事做,等前一件做完了才能做下一件事）
                                            例如普通B/S模式（同步）：提交请求->等待服务器处理->处理完毕返回 这个期间客户端浏览器不能干任何事　

                    阻塞：没有收完数据函数不返回，线程也被挂起；
                                        阻塞调用是指调用结果返回之前，当前线程会被挂起（线程进入非可执行状态，在这个状态下，cpu不会给线程分配时间片，即线程暂停运行）。函数只有在得到结果之后才会返回
                    异步：函数立即返回，通过事件或是信号通知调用者；　
                                        （  异步的概念和同步相对。当一个异步过程调用发出后，调用者不能立刻得到结果。实际处理这个调用的部件在完成后，通过状态、通知和回调来通知调用者。）　　
                                         例如 ajax请求（异步）: 请求通过事件触发->服务器处理（这时浏览器仍然可以做其他事情）->处理完毕　

                    非阻塞：函数立即返回，通过select通知调用者
                                        非阻塞和阻塞的概念相对应，指在不能立刻得到结果之前，该函数不会阻塞当前线程，而会立刻返回。


 1. 同步，就是我调用一个功能，该功能没有结束前，我死等结果。
 2. 异步，就是我调用一个功能，不需要知道该功能结果，该功能有结果后通知我（回调通知）；【调用后，我就不管了，我去做我的事，有结果   会自动通知我(回调)】
 3. 阻塞，      就是调用我（函数），我（函数）没有接收完数据或者没有得到结果之前，我（函数）不会返回。
 4. 非阻塞，  就是调用我（函数），我（函数）立即返回，通过select通知调用者
 */
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    /**
     * 点击按钮按钮 发起 GET 请求
     */
    public void okHttpget(View view) {
        okHttpGet();
    }

    /**
     *  okhttp GET 请求
     *  如果：访问网络报错：No Network Security Config specified, using platform default
     *  有可能是你写错网址了，或Https写成了Http了
     */
    public void okHttpGet() {
        /**  n1.首先创建 OKHttpClient 对象*/
        OkHttpClient okHttpClient = new OkHttpClient();
        /** n2.创建一个请求 ： Requset   参数最起码有一个url 当然你可以通过Request.Builder设置更多的参数比如：header、method等。*/
        Request request = new Request
                .Builder()
                .url("https://ys.leiyu0001.cn/aiwo/ms-appWeb/index/typeList")
                .build();
        /** n3. 创建 呼叫 访问 ：Call  准备执行的代码请求
         *                     Call   是一个接口类型  还其他方法：
         isCanceled   是否取消的   booleans
         isExecuted   是否被执行   booleans
         cancel       取消        void
         enqueue      入队        void
         execute      执行        返回 Response 响应
         request      请求        返回 Request  请求
         * */
        Call call = okHttpClient.newCall(request);
        /** 支持 阻塞的方式  返回一个Respons*/
//        try {
//            final Response execute = call.execute();
//        } catch (IOException e) {
//            e.printStackTrace();
//        }

        /** n4. 请求加入 请求队列  enqueue  异步请求 并通过 Callback 回调返回*/
        call.enqueue(new Callback() {
            /** 当请求因:
             *         1. 取消而无法执行时，
             *         2.     连接问题或超时。
             *         3.           因为网络在交换期间可能失败，
             *  所以远程服务器是可能的。在失败之前接受请求。
             *          @param call
             *          @param e
             */
            @Override
            public void onFailure(Call call, IOException e) {   /** 目前是子线程 */
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(MainActivity.this,
                                "1. 取消而无法执行时，\n" +
                                        "    2.     连接问题或超时。\n" +
                                        "    3.           因为网络在交换期间可能失败", Toast.LENGTH_SHORT).show();

                    }
                });
                e.printStackTrace();
            }

            /** 当远程服务器成功返回HTTP响应时调用
             *  可以用响应：Response 读取响应体：body
             *  反应仍然存在直到 ResponseBody 响应体关闭
             *  回到接受者可以再另一个线程上使用响应体
             *  <P>注意传输层成功（接收HTTP响应代码、标头和正文）
             *  不一定指示应用程序层的成功：{@code response}仍然可以指示一个
             ＊  不愉快的HTTP响应代码，如404或500。             *
             *      @param call          呼叫  请求对象
             *      @param response      响应
             *      @throws IOException  IO流异常
             */
            @Override
            public void onResponse(Call call, Response response)   /** 这里不是UI线程*/
                    throws IOException {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(MainActivity.this,
                                "访问成功", Toast.LENGTH_SHORT).show();
                    }
                });
                /**onResponse回调的参数是response，一般情况下，比如我们希望获得返回的
                 *      字符串，可以通过response.body().string()获取；
                 *      二进制字节数组，则调用response.body().bytes()；
                 *      返回的inputStream，则调用response.body().byteStream()*/
                Log.i("NetWord", "响应体： " + response.body().string());
            }
        });
    }

    /** OkHttp 进行get请求下载文件
     *          除了上面的功能,我们最常用的功能该有从网路上下载文件,
     *          我们下面的例子将演示下载一个文件存放在存储卡根目录,
     *          从网络下载一张图片并显示到ImageView中
     1 . 从网络下载一个文件(此处我们以下载一张图片为例)
     *
     * */
    public void downloadImg(View view){
        OkHttpClient client = new OkHttpClient();
        final Request request = new Request.Builder()
                .get()
                .url("https://www.baidu.com/img/bd_logo1.png")
                .build();
        Call call = client.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.e("moer", "onFailure: ");;
            }

            @Override
            public void onResponse(Call call, Response response)
                    throws IOException {
                /**你会发现步骤与进行一般的Get请求差别不大,唯一的区别在于我们在回调函数中所做的事,我们拿到了图片的字节流,然后保存为了本地的一张图片*/
                //拿到字节流
                InputStream is = response.body().byteStream();

                int len = 0;
                File file  = new File(Environment.getExternalStorageDirectory(), "n.png");
                FileOutputStream fos = new FileOutputStream(file);
                byte[] buf = new byte[128];

                while ((len = is.read(buf)) != -1){
                    fos.write(buf, 0, len);
                }

                fos.flush();
                //关闭流
                fos.close();
                is.close();
                /**然下面是另一种方法
                 这里我们使用BitmapFactory的decodeStream将图片的输入流直接转换为Bitmap,然后设置到ImageView中,下面只给出onResponse()中的代码.*/
//                final Bitmap bitmap = BitmapFactory.decodeStream(is);
//                runOnUiThread(new Runnable() {
//                    @Override
//                    public void run() {
//                        imageView.setImageBitmap(bitmap);
//                    }
//                });
//
//                is.close();


            }
        });
    }



    public void okHttpNext(View view) {
        startActivity(new Intent(this,PostActivity.class));
    }

    public void nextdownload(View view) {
        startActivity(new Intent(this,DownloadUploadProgressActivity.class));
    }

    public void nexthttpssll(View view) {
        startActivity(new Intent(this,OKHttpsSLLActivity.class));
    }

    public void renzhengqingqui(View view) throws Exception {


      run();




    }



    public void run() throws Exception {

        final String basic = Credentials.basic("admin", "public");
        OkHttpClient client = new OkHttpClient.Builder()
                        .authenticator(new Authenticator() {
                            public Request authenticate(Route route, Response response) throws IOException {
                                System.out.println("Authenticating for response: " + response);
                                System.out.println("Challenges: " + response.challenges());
                                return response.request().newBuilder().header("Authorization", basic).build();

                            }
                        })
                        .build();

        Request request = new Request.Builder()
                .url("http://192.168.31.97:18083/api/v2/clients/12345")
                .build();

        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.d("--------", "onFailure: "+e.getMessage());
            }


            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.isSuccessful()) {
                    Log.d("---------", "onResponse: "+response.body().string());
                }
            }
        });

    }

}
